package com.dage;

import com.alibaba.excel.util.MapUtils;
import com.jfinal.plugin.activerecord.generator.ColumnMeta;
import com.jfinal.plugin.activerecord.generator.MetaBuilder;
import com.jfinal.plugin.activerecord.generator.TableMeta;

import javax.sql.DataSource;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.*;

/**
 * 自定义数据表元数据，用于自定义映射特定字段为指定类型
 */
public class MyMetaBuilder extends MetaBuilder {
	public Map<String, Class> columnTypeMapping = new HashMap<>();
	private Set<String> publicColumns;
	private boolean extendsBase;
	private Map<String, Map<String, ExcelColumnMeta>> tableInfo;

	public MyMetaBuilder(DataSource dataSource) {
		super(dataSource);
		extendsBase = true;
		//公共字段
		publicColumns = new HashSet<>();
		publicColumns.add("id");
		publicColumns.add("create_user");
		publicColumns.add("create_time");
		publicColumns.add("update_user");
		publicColumns.add("update_time");
		publicColumns.add("is_deleted");

		//自定义字段类型映射
		columnTypeMapping.put("is_deleted", Byte.class);
		//数据表字段约束信息

		tableInfo = MapUtils.newHashMap();
		Map<String, ExcelColumnMeta> columns = MapUtils.newHashMap();
		ExcelColumnMeta columnMeta = new ExcelColumnMeta();
		//============product_profile============
		columnMeta.uniqueKey = true;
		columnMeta.withDataScope = false;
		columnMeta.notNull = true;
		columns.put("code", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.notNull = true;
		columns.put("name", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.dictKey = true;
		columnMeta.dictKeyType = "Dict.PRODUCT_UNIT_KEY";
		columns.put("unit", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.dictKey = true;
		columnMeta.dictKeyType = "Dict.PRODUCT_SPEC_KEY";
		columns.put("spec", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.dictKey = true;
		columnMeta.dictKeyType = "Dict.PRODUCT_TYPE_KEY";
		columns.put("type", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.enumProp = true;
		columnMeta.yesNo = true;
		columns.put("is_medical", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.enumProp = true;
		columnMeta.yesNo = true;
		columns.put("is_basic_drug", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.foreignKey = true;
		columnMeta.foreignKeyNotNull = false;
		columnMeta.foreignTable = "t_area";
		columnMeta.foreignColumn = "name";
		columnMeta.logicDelete = false;
		columnMeta.withDataScope = false;
		columns.put("area_id", columnMeta);

		tableInfo.put("product_profile", columns);

		//============t_user============
		columns = MapUtils.newHashMap();

		columnMeta = new ExcelColumnMeta();
		columnMeta.uniqueKey = true;
		columnMeta.logicDelete = false;
		columnMeta.withDataScope = false;
		columnMeta.notNull = true;
		columns.put("code", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.uniqueKey = true;
		columnMeta.notNull = true;
		columns.put("name", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.foreignKey = true;
		columnMeta.foreignTable = "t_role";
		columnMeta.foreignColumn = "role_name";
		columnMeta.logicDelete = false;
		columnMeta.withDataScope = false;
		columns.put("role_id", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.foreignKey = true;
		columnMeta.foreignTable = "t_area";
		columnMeta.foreignColumn = "name";
		columnMeta.logicDelete = false;
		columnMeta.withDataScope = false;
		columns.put("area_id", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.regexValidate = true;
		columnMeta.regexPattern = "ValidationInfo.REG_MOBILE";
		columns.put("phone", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.regexValidate = true;
		columnMeta.regexPattern = "ValidationInfo.REG_EMAIL";
		columns.put("email", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.regexValidate = true;
		columnMeta.regexPattern = "ValidationInfo.REG_ID_CARD";
		columns.put("id_number", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.enumProp = true;
		columnMeta.props = new String[]{"封停", "正常"};
		columns.put("status", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.enumProp = true;
		columnMeta.props = new String[]{"离职", "在职"};
		columns.put("work_status", columnMeta);

		columnMeta = new ExcelColumnMeta();
		columnMeta.enumProp = true;
		columnMeta.props = new String[]{"女", "男"};
		columns.put("sex", columnMeta);

		tableInfo.put("t_user", columns);
	}

	@Override
	protected String handleJavaType(String typeStr, ResultSetMetaData rsmd, int column) throws SQLException {
		String javaType = super.handleJavaType(typeStr, rsmd, column);
		Class clazz = columnTypeMapping.get(rsmd.getColumnName(column));
		if (clazz != null) {
			return clazz.getName();
		} else {
			return javaType;
		}
	}

	public List<TableMeta> build() {
		return build(false);
	}

	public List<TableMeta> build(boolean forExcel) {
		List<TableMeta> tableMetas = super.build();
		for (TableMeta tableMeta : tableMetas) {
			Map<String, ExcelColumnMeta> columnMetaMap = tableInfo.get(tableMeta.name);
			if (columnMetaMap == null) {
				columnMetaMap = MapUtils.newHashMap();
			}
			List<ColumnMeta> columnMetas = new ArrayList<>();
			for (ColumnMeta columnMeta : tableMeta.columnMetas) {
				//移除一些公共字段，因为已经在BaseModel中声明了
				if (extendsBase && publicColumns.contains(columnMeta.name)) {
					continue;
				}
				if (!columnMeta.name.equals(tableMeta.primaryKey)) {//排除主键
					if (!forExcel) {
						columnMetas.add(columnMeta);
						continue;
					}
					ExcelColumnMeta excelColumnMeta = columnMetaMap.get(columnMeta.name);
					if (excelColumnMeta == null) {
						excelColumnMeta = new ExcelColumnMeta();
					}
					excelColumnMeta.name = columnMeta.name;
					excelColumnMeta.attrName = columnMeta.attrName;
					excelColumnMeta.javaType = columnMeta.javaType;
					excelColumnMeta.remarks = columnMeta.remarks;
					columnMetas.add(excelColumnMeta);

					//日期类型处理
					if (excelColumnMeta.javaType.contains("Date")) {
						excelColumnMeta.excelIgnore = true;
						ExcelColumnMeta ecm = new ExcelColumnMeta();
						ecm.attrName = columnMeta.attrName + "Str";
						ecm.javaType = "java.lang.String";
						ecm.remarks = columnMeta.remarks;
						ecm.dateStr = true;
						columnMetas.add(ecm);
					} else if (excelColumnMeta.foreignKey || excelColumnMeta.dictKey || excelColumnMeta.enumProp) {
						//外键约束、字典、枚举字段
						excelColumnMeta.excelIgnore = true;
						ExcelColumnMeta ecm = new ExcelColumnMeta();
						if (excelColumnMeta.foreignKey || excelColumnMeta.dictKey) {
							ecm.attrName = columnMeta.attrName + "Str";
							if (excelColumnMeta.foreignKey) {
								ecm.foreignKeyStr = true;
								ecm.foreignKeyNotNull = excelColumnMeta.foreignKeyNotNull;
							} else {
								ecm.dictKeyStr = true;
								ecm.dictKeyNotNull = excelColumnMeta.dictKeyNotNull;
							}
						} else {
							ecm.attrName = columnMeta.attrName + "Name";
							ecm.enumPropName = true;
						}
						ecm.javaType = "java.lang.String";
						ecm.remarks = columnMeta.remarks;
						columnMetas.add(ecm);
					}
				}
			}
			tableMeta.columnMetas = columnMetas;
		}
		return tableMetas;
	}
}
